package com.ta.gulimall.ware.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ta.gulimall.common.enums.PurchaseDetailEnums;
import com.ta.gulimall.common.enums.PurchaseStatusEnums;
import com.ta.gulimall.common.utils.system.PageUtils;
import com.ta.gulimall.common.utils.system.Query;
import com.ta.gulimall.ware.service.PurchaseDetailService;
import com.ta.gulimall.ware.service.WareSkuService;
import com.ta.gulimall.ware.view.entity.PurchaseDetailEntity;
import com.ta.gulimall.ware.view.vo.FinishPurchaseVo;
import com.ta.gulimall.ware.view.vo.MergePurchaseVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ta.gulimall.ware.dao.PurchaseDao;
import com.ta.gulimall.ware.view.entity.PurchaseEntity;
import com.ta.gulimall.ware.service.PurchaseService;
import org.springframework.transaction.annotation.Transactional;


@Service("purchaseService")
public class PurchaseServiceImpl extends ServiceImpl<PurchaseDao, PurchaseEntity> implements PurchaseService {

    @Autowired
    PurchaseDetailService purchaseDetailService;
    @Autowired
    WareSkuService wareSkuService;

    @Override
    public PageUtils listNoReceivePurchase(Map<String, Object> params) {
        LambdaQueryWrapper<PurchaseEntity> wrapper = new LambdaQueryWrapper<PurchaseEntity>()
                .eq(PurchaseEntity::getStatus, PurchaseStatusEnums.NEW_PURCHASE).or().eq(PurchaseEntity::getStatus, PurchaseStatusEnums.ALLOCATED_PURCHASE);
        IPage<PurchaseEntity> page = this.page(new Query<PurchaseEntity>().getPage(params), wrapper);

        return new PageUtils(page);
    }

    @Transactional
    @Override
    public void mergePurchase(MergePurchaseVo mergePurchaseVo) {
        Long purchaseId = mergePurchaseVo.getPurchaseId();
        if (ObjectUtil.isNull(purchaseId)) {
            PurchaseEntity purchase = new PurchaseEntity().setStatus(PurchaseStatusEnums.NEW_PURCHASE);
            this.save(purchase);
            purchaseId = purchase.getId();
        }

        Long finalPurchaseId = purchaseId;
        List<PurchaseDetailEntity> purchaseDetails = mergePurchaseVo.getItems().stream()
                .map(m -> new PurchaseDetailEntity()
                        .setPurchaseId(finalPurchaseId)
                        .setStatus(PurchaseDetailEnums.ALLOT)
                        .setId(m))
                .collect(Collectors.toList());

        purchaseDetailService.updateBatchById(purchaseDetails);
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void receivedPurchase(List<Long> purchaseIds) {
        List<PurchaseEntity> purchases = purchaseIds.stream().map(m -> Optional.ofNullable(getById(m)).orElse(new PurchaseEntity()))
                .filter(f -> PurchaseStatusEnums.NEW_PURCHASE.equals(f.getStatus()) || PurchaseStatusEnums.ALLOCATED_PURCHASE.equals(f.getStatus()))
                .map(m -> new PurchaseEntity()
                        .setId(m.getId())
                        .setStatus(PurchaseStatusEnums.DRAW_PURCHASE))
                .collect(Collectors.toList());

        updateBatchById(purchases);

        purchaseIds = purchases.stream().map(PurchaseEntity::getId).collect(Collectors.toList());
        List<PurchaseDetailEntity> purchaseDetails = purchaseDetailService.listPurchaseDetail(purchaseIds);

        purchaseDetails = purchaseDetails.stream()
                .map(m -> new PurchaseDetailEntity()
                        .setStatus(PurchaseDetailEnums.PURCHASE)
                        .setId(m.getId()))
                .collect(Collectors.toList());

        purchaseDetailService.updateBatchById(purchaseDetails);
    }

    @Override
    @Transactional
    public void donePurchase(FinishPurchaseVo purchaseVo) {
        AtomicReference<Boolean> is = new AtomicReference<>(Boolean.TRUE);

        ArrayList<PurchaseDetailEntity> list = new ArrayList<>();
        purchaseVo.getItems().forEach(f -> {
            PurchaseDetailEntity detail = new PurchaseDetailEntity();
            if (PurchaseDetailEnums.FAIL.equals(f.getPurchaseDetailEnums())) {
                detail.setStatus(PurchaseDetailEnums.FAIL);
                is.set(Boolean.FALSE);
            }else{
                detail.setStatus(PurchaseDetailEnums.ACCOMPLISH);
                wareSkuService.addWareSku(purchaseDetailService.getById(f.getItemId()));
            }
            list.add(detail.setId(f.getItemId()));
        });
        purchaseDetailService.updateBatchById(list);

        updateById(new PurchaseEntity().setId(purchaseVo.getId()).setStatus(is.get() ? PurchaseStatusEnums.COMPLETE_PURCHASE : PurchaseStatusEnums.ABNORMAL_PURCHASE));

    }

}